assume cs:code
stack segment
	db 128 dup (0)
stack ends
data segment
	dw 0,0
data ends
code segment
start: mov ax,stack
	   mov ss,ax
	   mov sp,128

	   mov ax,data
	   mov ds,ax
	   
	   mov ax,0
	   mov es,ax
	   
	   push es:[9*4]
	   pop ds:[0]
	   push es:[9*4+2]
	   pop ds:[2] ;pre int9 entry save to ds:0 ds:2
	   
	   CLI ;屏蔽-可屏蔽中断
	   mov word ptr es:[9*4],offset int9 ;now int9 entry 如果这里发生了中断
	   mov es:[9*4+2],cs ;而原INT9的高位不是CS段，就跳到一个未知地方去了，所以这里需要加锁
	   STI ;接收-可屏蔽中断
	   
	   mov ax,0b800h
	   mov es,ax
	   mov ah,'a'
	s: mov es:[160*12+40*2],ah
	   call delay
	   inc ah
	   cmp ah,'z'
	   jna s
	   
	   mov ax,0
	   mov es,ax
	   
	   push ds:[0]
	   pop es:[9*4]
	   push ds:[2]
	   pop es:[9*4+2] ;revert pre int9 entry
	   
	   mov ax,4c00h
	   int 21h
	   
delay: push ax
	   push dx
	   mov dx,10h
	   mov ax,0
s1:    sub ax,1
	   sbb dx,0
	   cmp ax,0
	   jne s1
	   cmp dx,0
	   jne s1
	   pop dx
	   pop ax
	   ret

int9: push ax
	  push bx
	  push es
	  
	  in al,60h
	  
	  pushf             ;可精简为 pushf
	  pushf				;call dword ptr ds:[0]
	  pop bx			;因为原INT9会有一个IRET，所以这里需要一个pushf
	  and bh,11111100b  ;没有不一定有问题，但有是肯定没问题
	  push bx
	  popf
	  call dword ptr ds:[0]
	  
	  cmp al,1
	  jne int9ret
	  
	  mov ax,0b800h
	  mov es,ax
	  inc byte ptr es:[160*12+40*2+1]
	  
int9ret: pop es
		 pop bx
		 pop ax
		 iret
		 
code ends
end start
	   
	   
code ends
end start	   